/*
Yaaic - Yet Another Android IRC Client

Copyright 2009-2011 Sebastian Kaspari

This file is part of Yaaic.

Yaaic is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Yaaic is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Yaaic.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.yaaic.activity;

import java.util.ArrayList;
import java.util.List;

import org.yaaic.R;
import org.yaaic.Yaaic;
import org.yaaic.adapter.ServerListAdapter;
import org.yaaic.db.Database;
import org.yaaic.gps_utils.ChannelCollection;
import org.yaaic.gps_utils.LocationObj;
import org.yaaic.irc.IRCBinder;
import org.yaaic.irc.IRCService;
import org.yaaic.layout.NonScalingBackgroundDrawable;
import org.yaaic.listener.ServerListener;
import org.yaaic.model.Authentication;
import org.yaaic.model.Broadcast;
import org.yaaic.model.Channel;
import org.yaaic.model.Extra;
import org.yaaic.model.Identity;
import org.yaaic.model.Server;
import org.yaaic.model.Status;
import org.yaaic.receiver.ServerReceiver;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

/**
 * List of servers
 * 
 * @author Sebastian Kaspari <sebastian@yaaic.org>
 */
public class ServersActivity extends ListActivity implements ServiceConnection, ServerListener, OnItemLongClickListener, OnClickListener {
    private IRCBinder binder;
    private ServerReceiver receiver;
    private ServerListAdapter adapter;
    private ListView list;
    private static int instanceCount = 0;

    // New variables
    // v v v v v v v v v v v v v v v v v v v v v v v v v v
    private TextView gpsText;
    private TextView chanText;
    LocationManager locationManager;
    LocationListener locationListener;

    private Button joinLocal, findNear, browseAll;

    private Authentication authentication;
    private ArrayList<String> aliases;
    private ArrayList<Channel> channels;
    private ArrayList<String> commands;
    private Server server;

    private String gotNickName;

    // ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^

    /**
     * On create
     */

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        /*
         * With activity:launchMode = standard, we get duplicated activities
         * depending on the task the app was started in. In order to avoid
         * stacking up of this duplicated activities we keep a count of this
         * root activity and let it finish if it already exists
         * 
         * Launching the app via the notification icon creates a new task,
         * and there doesn't seem to be a way around this so this is needed
         */
        if (instanceCount > 0) {
            finish();
        }
        instanceCount++;
        setContentView(R.layout.servers);

        adapter = new ServerListAdapter();
        setListAdapter(adapter);

        list = getListView();
        list.setOnItemLongClickListener(this);
        list.setBackgroundDrawable(new NonScalingBackgroundDrawable(this, list, R.drawable.background));

        // TODO delete
        gpsText = (TextView) findViewById(R.id.gpsText);
        chanText = (TextView) findViewById(R.id.chanText);
        gpsText.setText("GPS: loading...");
        gpsTestSetup();

        joinLocal = (Button) findViewById(R.id.bJoinLocal);
        findNear = (Button) findViewById(R.id.bFindNear);
        browseAll = (Button) findViewById(R.id.bBrowseAll);

        joinLocal.setOnClickListener(this);
        findNear.setOnClickListener(this);
        browseAll.setOnClickListener(this);

        //        Yaaic y = new Yaaic();
        Database db = new Database(this);
        if(db.getServers().isEmpty()){

            Log.d("inGetData", "0 is here");
            getData();
            addServerActivitySetup();
            addPresetServers(gotNickName, gotNickName);

        }

    }

    private void getData() {
        // TODO Auto-generated method stub
        Log.d("inGetData", "1 is here");
        Bundle gotBasket = getIntent().getExtras();
        Log.d("inGetData", "2 is here");
        gotNickName = gotBasket.getString("key");
        Log.d("inGetData", "3 plus nick is here " + gotNickName);

    }

    public void addServerActivitySetup()
    {

        authentication = new Authentication();
        aliases = new ArrayList<String>();
        channels = new ArrayList<Channel>();
        commands = new ArrayList<String>();

        Bundle extras = getIntent().getExtras();
        if (extras != null && extras.containsKey(Extra.SERVER)) {
            // Request to edit an existing server
            Database db = new Database(this);
            this.server = db.getServerById(extras.getInt(Extra.SERVER));
            aliases.addAll(server.getIdentity().getAliases());
            this.channels = db.getChannelsByServerId(server.getId());
            this.commands = db.getCommandsByServerId(server.getId());
            this.authentication = server.getAuthentication();
            db.close();
        }

    }


    /**
     * Add Preset Servers to database
     */
    public void addPresetServers(String nickName, String realName)
    {
        Database db = new Database(this);

        Identity identity = new Identity();
        identity.setNickname(nickName);
        identity.setIdent("yaaic");
        identity.setRealName(realName);

        Log.d("In AddServerPresets", identity.getNickname() + " Nickname is here");
        Log.d("In AddServerPresets", identity.getIdent() + " Ident is here");
        Log.d("In AddServerPresets", identity.getRealName() + " RealName is here");
        Log.d("In AddServerPresets", "|" + identity.getAliases() + "| Aliases is here");

        identity.setAliases(aliases);

        long identityId = db.addIdentity(
            identity.getNickname(),
            identity.getIdent(),
            identity.getRealName(),
            identity.getAliases()
        );

        Log.d("In AddServerActivity", identityId + " identityId is here");

        Server server = setPresetServer("AAA", "irc.rizon.net", 6667, "", "UTF-8", false);
        server.setAuthentication(authentication);

        long serverId = db.addServer(server, (int) identityId);

        db.setChannels((int) serverId, channels);
        db.setCommands((int) serverId, commands);

        db.close();

        server.setId((int) serverId);
        server.setIdentity(identity);
        server.setAutoJoinChannels(channels);
        server.setConnectCommands(commands);

        Yaaic.getInstance().addServer(server);
    }


    private Server setPresetServer(String title, String host, int port, String password, String charset, Boolean useSSL)
    {
        Server server = new Server();
        server.setHost(host);
        server.setPort(port);
        server.setPassword(password);
        server.setTitle(title);
        server.setCharset(charset);
        server.setUseSSL(false);
        server.setStatus(Status.DISCONNECTED);

        return server;
    }

    // GPS Method should compile if you can import Location.*
    // v v v v v v v v v v v v v v v v v v v v v v v v v v
    private void gpsTestSetup() {
        locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

        // Define a listener that responds to location updates
        locationListener = new LocationListener() {

            @Override
            public void onLocationChanged(Location location) {
                LocationObj loc = new LocationObj(location.getLatitude(), location.getLongitude());
                gpsText.setText("GPS:\n" + loc.toString());
                List<Channel> chans = ChannelCollection.getChannelsByDistance(loc, 10);
                StringBuilder sb = new StringBuilder();
                for (Channel c : chans) {
                    sb.append(c.getName()).append("\n");
                }
                chanText.setText(sb.toString());
                locationManager.removeUpdates(locationListener);
            }


            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {
            }


            @Override
            public void onProviderEnabled(String provider) {
            }


            @Override
            public void onProviderDisabled(String provider) {}
        };

        // Register the listener with the Location Manager to receive location updates
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 10, locationListener);
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 10, locationListener);
    }
    // ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^

    /**
     * On Destroy
     */

    @Override
    public void onDestroy()
    {
        super.onDestroy();
        //        deleteServers();
        instanceCount--;
    }

    /**
     * On resume
     */

    @Override
    public void onResume()
    {
        //        addServerActivitySetup();
        //        addPresetServers();
        super.onResume();

        // Start and connect to service
        Intent intent = new Intent(this, IRCService.class);
        intent.setAction(IRCService.ACTION_BACKGROUND);
        startService(intent);
        bindService(intent, this, 0);

        receiver = new ServerReceiver(this);
        registerReceiver(receiver, new IntentFilter(Broadcast.SERVER_UPDATE));

        adapter.loadServers();
    }

    /**
     * On pause
     */

    @Override
    public void onPause()
    {
        //        deleteServers();
        super.onPause();

        if (binder != null && binder.getService() != null) {
            binder.getService().checkServiceStatus();
        }


        unbindService(this);
        unregisterReceiver(receiver);
    }

    /**
     * Service connected to Activity
     */

    @Override
    public void onServiceConnected(ComponentName name, IBinder service)
    {
        binder = (IRCBinder) service;
    }

    /**
     * Service disconnected from Activity
     */

    @Override
    public void onServiceDisconnected(ComponentName name)
    {
        binder = null;
    }

    /**
     * On server selected
     * WILL BE REMOVED FOR A 'onClick' METHOD LATER
     */

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {

        Server server = adapter.getItem(position);

        if (server == null) {
            // "Add server" was selected
            //            startActivityForResult(new Intent(this, AddServerActivity.class), 0);
            return;
        }

        Intent intent = new Intent(this, ConversationActivity.class);

        if (server.getStatus() == Status.DISCONNECTED && !server.mayReconnect()) {
            server.setStatus(Status.PRE_CONNECTING);
            intent.putExtra("connect", true);
        }

        intent.putExtra("serverId", server.getId());
        startActivity(intent);

    }


    @Override
    public void onClick(View v) {
        Log.d("WOW!", "here is now");

        //        Object o = null;
        //        o.equals(null);

        switch (v.getId()){
            case R.id.bJoinLocal:
                Log.d("Here", "here is join local!");


                Class ourClass;
                try {
                    ourClass = Class.forName("org.yaaic.activity.UserInfoActivity");
                    Intent ourIntent = new Intent(ServersActivity.this, ourClass);
                    startActivity(ourIntent);
                }
                catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }


                //Server = nearest location.
                //so, server = server.getServerById(loc.getserverid());
                //                Server server = adapter.getItem(position);
                /*
                if (server == null) {
                    // "Add server" was selected
                    //            startActivityForResult(new Intent(this, AddServerActivity.class), 0);
                    return;
                }

                Intent intent = new Intent(this, ConversationActivity.class);

                if (server.getStatus() == Status.DISCONNECTED && !server.mayReconnect()) {
                    server.setStatus(Status.PRE_CONNECTING);
                    intent.putExtra("connect", true);
                }

                intent.putExtra("serverId", server.getId());
                startActivity(intent);

                 */
                break;

            case R.id.bFindNear:
                Log.d("Here", "here is find near");
                Class findNearClass;
                try {
                    findNearClass = Class.forName("org.yaaic.activity.FindNearbyActivity");
                    Intent ourIntent = new Intent(ServersActivity.this, findNearClass);
                    startActivity(ourIntent);
                }
                catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                break;
            case R.id.bBrowseAll:
                Log.d("Here", "here is browse all");
                break;

        }

    }

    /**
     * On long click
     */

    @Override
    public boolean onItemLongClick(AdapterView<?> l, View v, int position, long id)
    {

        final Server server = adapter.getItem(position);

        if (server == null) {
            // "Add server" view selected
            return true;
        }

        final CharSequence[] items = {
            getString(R.string.connect),
            getString(R.string.disconnect),
            getString(R.string.edit),
            getString(R.string.delete)
        };

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(server.getTitle());
        builder.setItems(items, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int item) {
                switch (item) {
                    case 0: // Connect
                        if (server.getStatus() == Status.DISCONNECTED) {
                            binder.connect(server);
                            server.setStatus(Status.CONNECTING);
                            adapter.notifyDataSetChanged();
                        }
                        break;
                    case 1: // Disconnect
                        server.clearConversations();
                        server.setStatus(Status.DISCONNECTED);
                        server.setMayReconnect(false);
                        binder.getService().getConnection(server.getId()).quitServer();
                        break;
                    case 2: // Edit
                        //                        editServer(server.getId());
                        break;
                    case 3: // Delete
                        binder.getService().getConnection(server.getId()).quitServer();
                        deleteServer(server.getId());
                        break;
                }
            }
        });
        AlertDialog alert = builder.create();
        alert.show();

        return true;

    }

    /**
     * Start activity to edit server with given id
     * 
     * @param serverId The id of the server
     */
    //    private void editServer(int serverId)
    //    {
    //        Server server = Yaaic.getInstance().getServerById(serverId);
    //
    //        if (server.getStatus() != Status.DISCONNECTED) {
    //            Toast.makeText(this, getResources().getString(R.string.disconnect_before_editing), Toast.LENGTH_SHORT).show();
    //        }
    //        else {
    //            Intent intent = new Intent(this, AddServerActivity.class);
    //            intent.putExtra(Extra.SERVER, serverId);
    //            startActivityForResult(intent, 0);
    //        }
    //    }

    /**
     * Options Menu (Menu Button pressed)
     */

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        super.onCreateOptionsMenu(menu);

        // inflate from xml
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.servers, menu);

        return true;
    }

    /**
     * On menu item selected
     */

    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item)
    {
        /*
        switch (item.getItemId()) {
            case R.id.add:
                //                startActivityForResult(new Intent(this, AddServerActivity.class), 0);
                break;
            case R.id.about:
                startActivity(new Intent(this, AboutActivity.class));
                break;
            case R.id.settings:
                startActivity(new Intent(this, SettingsActivity.class));
                break;
            case R.id.exit:
                ArrayList<Server> mServers = Yaaic.getInstance().getServersAsArrayList();
                for (Server server : mServers) {
                    if (binder.getService().hasConnection(server.getId())) {
                        server.setStatus(Status.DISCONNECTED);
                        server.setMayReconnect(false);
                        binder.getService().getConnection(server.getId()).quitServer();
                    }
                }
                // ugly
                binder.getService().stopForegroundCompat(R.string.app_name);
                finish();
        }
         */
        return true;
    }

    /**
     * On activity result
     */

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        if (resultCode == RESULT_OK) {
            // Refresh list from database
            adapter.loadServers();
        }
    }

    /**
     * Delete server
     * 
     * @param serverId
     */
    public void deleteServer(int serverId)
    {
        Database db = new Database(this);
        db.removeServerById(serverId);

        db.close();

        Yaaic.getInstance().removeServerById(serverId);
        adapter.loadServers();
    }

    /** Delete server
     * 
     * @param serverId
     */
    public void deleteServers()
    {

        //        for(int serverId = 0; serverId<100; serverId++)
        //        {
        //
        //            Database db = new Database(this);
        //            if(db.getServerById(serverId)!= null)
        //            {
        //                db.removeServerById(serverId);
        //
        //                db.close();
        //
        //                Yaaic.getInstance().removeServerById(serverId);
        //                adapter.loadServers();
        //            }
        //            else{
        //                db.close();
        //            }
        //        }

    }





    /**
     * On server status update
     */

    @Override
    public void onStatusUpdate()
    {
        adapter.loadServers();

        if (adapter.getCount() > 2) {
            // Hide background if there are servers in the list
            list.setBackgroundDrawable(null);
        }
    }

}